home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 November
/
Macworld (1999-11).dmg
/
Updaters
/
WhiteCap 3.0.4
/
WhiteCap Source.sit
/
WhiteCap Source
/
Common
/
Graphics
/
PixPort.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-08-28
|
37KB
|
1,593 lines
#include "PixPort.h"
#include <math.h>
#if EG_MAC
#include <QuickDraw.h>
#include <QDOffscreen.h>
#include <Displays.h>
#include <string.h>
#endif
long PixPort::sOSDepth = 16;
long PixPort::sMinDepth = 16;
long PixPort::sCanFullscreen = false;
void PixPort::Startup() {
#if EG_MAC
#if USE_DRAW_SPROCKETS
OSStatus err = ::DSpStartup();
sCanFullscreen = err == 0;
#else
sCanFullscreen = false;
#endif
GDHandle gDevice = ::GetMainDevice();
if ( gDevice )
sOSDepth = (**(**gDevice).gdPMap).pixelSize;
else
sOSDepth = 16;
#endif
#if EG_WIN
#if USE_DIRECTX
sCanFullscreen = true;
#else
sCanFullscreen = false;
#endif
HDC hdc = ::GetDC( NULL );
sOSDepth = ::GetDeviceCaps( hdc, BITSPIXEL );
::ReleaseDC( NULL, hdc );
#endif
}
void PixPort::Shutdown() {
#if USE_DRAW_SPROCKETS
if ( sCanFullscreen )
::DSpShutdown();
#endif
}
PixPort::PixPort() {
mBM = NULL;
mWorld = NULL;
mX = 0;
mY = 0;
mLineWidth = 1;
mBackColor = 0;
mContextRef = 0;
mBytesPerPix = 0;
#if EG_WIN
mWorld = ::CreateCompatibleDC( NULL );
mBM = NULL;
mDDObj = NULL;
#endif
#if EG_MAC
mHndlSize = 0;
mTempHndl = NULL;
#endif
}
PixPort::~PixPort() {
if ( IsFullscreen() )
Deactivate();
#if EG_MAC
if ( mWorld ) {
::UnlockPixels( mBM );
::DisposeGWorld( mWorld );
}
OSErr err;
if ( mTempHndl )
::TempDisposeHandle( mTempHndl, &err );
#elif EG_WIN
if ( mWorld )
::DeleteDC( mWorld );
if ( mBM )
::DeleteObject( mBM );
#endif
}
long PixPort::GetOwningDisplay( const Point& inPt ) {
#if EG_MAC
OSStatus err;
DisplayIDType id = 0;
GDHandle theGDevice;
/*
** Walk the list of display devices in the system. DrawSprocket is
** centered around the DisplayIDType, which is used by the Display
** Manager. The GDevice records are going to be in flux with future
** versions of the system software, so it is best to make the change
** now and make your software DisplayManager-centric.
*/
theGDevice = DMGetFirstScreenDevice( false );
while( theGDevice && ! id ) {
if ( ::PtInRect( inPt, &(**theGDevice).gdRect ) ) {
/* get the display ID */
err = DMGetDisplayIDByGDevice( theGDevice, &id, false );
if ( err )
id = 0;
}
/* next device */
theGDevice = DMGetNextScreenDevice( theGDevice, false );
}
/*
err = ::DSpFindContextFromPoint( inPt, &ref );
if ( ! err )
err = ::DSpContext_GetDisplayID( ref, &id );
*/
return ( err ) ? 0 : id;
#endif
#if EG_WIN
#pragma unused ( inPt )
return 0;
#endif
}
void PixPort::UnionDirtyRect( const Rect* inDirtyRect ) {
#if EG_MAC
#if USE_DRAW_SPROCKETS
if ( IsFullscreen() )
::DSpContext_InvalBackBufferRect( mContextRef, inDirtyRect );
#else
#pragma unused ( inDirtyRect )
#endif
#endif
#if EG_WIN && USE_DIRECTX
if ( IsFullscreen() ) {
long w, h;
HDC hdc;
w = inDirtyRect -> right - inDirtyRect -> left;
h = inDirtyRect -> bottom - inDirtyRect -> top;
if ( mContextRef -> GetDC( &hdc ) == DD_OK ) {
::BitBlt( hdc, inDirtyRect -> left, inDirtyRect -> top, w, h, mWorld, inDirtyRect -> left, inDirtyRect -> top, SRCCOPY );
mContextRef -> ReleaseDC( hdc );
}
}
#endif
}
bool PixPort::InitFullscreen( int inDispNum, Point& outSize, WindowPtr inWin, int inBitDepth ) {
bool ok = false;
if ( inBitDepth != 8 || inBitDepth != 16 || inBitDepth != 32 )
inBitDepth = sOSDepth;
// If we're already at fullscreen
if ( IsFullscreen() ) {
if ( mBytesPerPix * 8 == inBitDepth )
return true;
else
Deactivate();
}
#if EG_MAC
#pragma unused( inWin )
#if USE_DRAW_SPROCKETS
DSpContextReference ref;
OSStatus err;
DSpContextAttributes context;
long bestWidth = 0x7FFFFFFF;
bool isInitted = false;
if ( sCanFullscreen ) {
err = ::DSpGetFirstContext( inDispNum, &ref );
// Look for smallest size w/ for given depth
while ( ! err ) {
err = DSpContext_GetAttributes( ref, &context );
if ( ! err ) {
if ( context.displayWidth <= bestWidth && context.displayWidth >= 640 ) {
if ( context.displayBestDepth == inBitDepth ) {
mContextRef = ref;
isInitted = true;
bestWidth = context.displayWidth;
}
}
}
// Try the next context for this display
err = ::DSpGetNextContext( ref, &ref );
}
if ( ! isInitted ) {
mContextRef = 0;
return false;
}
::DSpContext_GetAttributes( mContextRef, &mContext );
outSize.h = mContext.displayWidth;
outSize.v = mContext.displayHeight;
/*
** Here is where I need to OR in the value to use page flipping. If
** I had used the value when calling DSpFindBestContext() then it would
** have only considered displays that have page flipping hardware, but
** I want to run with software buffering too.
*/
mContext.contextOptions = kDSpContextOption_PageFlip;
mContext.frequency = 0;
mContext.reserved1 = 0;
mContext.reserved2 = 0;
mContext.gameMustConfirmSwitch = false;
mContext.reserved3[0] = 0;
mContext.reserved3[1] = 0;
mContext.reserved3[2] = 0;
mContext.reserved3[3] = 0;
mContext.colorTable = 0;
mContext.pageCount = 0;
mContext.colorNeeds = kDSpColorNeeds_Require;
// Try to reserve the device
err = ::DSpContext_Reserve( mContextRef, &mContext );
if ( err ) {
mContextRef = 0;
return false;
}
// If no errors, 'activate' the device into fullscreen
::HideCursor();
::DSpContext_FadeGammaOut( mContextRef, NULL );
err = ::DSpContext_SetState( mContextRef, kDSpContextState_Active );
if ( err )
::DSpContext_Release( mContextRef );
else {
BeginFrame();
// Load the key info about the fullscreen mode
if ( mBM ) {
// If we have an offscreen world allocated, chuck it
if ( mWorld ) {
::UnlockPixels( mBM );
::DisposeGWorld( mWorld );
mWorld = NULL;
}
mBytesPerRow = (**mBM).rowBytes & 0xFFF;
mBytesPerPix = (**mBM).pixelSize / 8;
mX = (**mBM).bounds.right - (**mBM).bounds.left;
mY = (**mBM).bounds.bottom - (**mBM).bounds.top - 1;
ok = true;
}
}
::DSpContext_FadeGamma( mContextRef, 100, NULL );
}
#else
#pragma unused( inDispNum, outSize )
#endif
#endif
#if EG_WIN
#pragma unused( inDispNum )
#if USE_DIRECTX
if ( sCanFullscreen ) {
HRESULT err = ::DirectDrawCreate( NULL, &mDDObj, NULL );
if ( err == DD_OK ) {
LPDIRECTDRAWSURFACE context;
err = mDDObj -> SetCooperativeLevel( inWin, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if ( err == DD_OK ) {
err = mDDObj -> SetDisplayMode( 640, 480, inBitDepth );
if ( err == DD_OK ) {
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
err = mDDObj -> CreateSurface( &ddsd, &context, NULL);
}
}
if ( err == DD_OK ) {
Init( 640, 480, inBitDepth );
mContextRef = context;
outSize.h = 640;
outSize.v = 480;
::SetForegroundWindow( inWin );
::SetCapture( inWin );
::ShowCursor( false );
ok = true; }
else {
mDDObj -> Release();
mDDObj = NULL;
}
}
}
#else
#pragma unused( outSize, inWin )
#endif
#endif
if ( ! ok )
mContextRef = 0;
return mContextRef;
}
void PixPort::Init( int inWidth, int inHeight, int inDepth ) {
if ( inWidth < 0 ) inWidth = 0;
if ( inHeight < 0 ) inHeight = 0;
// Catch any invalid depth levels.
if ( inDepth != 32 && inDepth != 16 && inDepth != 8 )
inDepth = sOSDepth;
// If we've been at full screen, take us out
if ( IsFullscreen() )
Deactivate();
else if ( mWorld && mBytesPerPix * 8 == inDepth && inWidth == mX && inHeight == mY )
return;
mX = 4 * (( inWidth + 3 ) / 4 );
mY = inHeight;
#if EG_MAC
// Save current draw envir
GDHandle saveDev;
GrafPtr savePort;
::GetGWorld( (GWorldPtr*)(&savePort), &saveDev );
if ( mWorld ) {
::UnlockPixels( mBM );
::DisposeGWorld( mWorld );
}
Rect r;
::SetRect( &r, 0, 0, mX, mY+1 );
::NewGWorld( &mWorld, inDepth, &r, NULL, NULL, useTempMem );
mBM = ::GetGWorldPixMap( mWorld );
//::LockPixels( mBM );
mBytesPerRow = (**mBM).rowBytes & 0xFFF;
mBytesPerPix = (**mBM).pixelSize / 8;
#if GFORCE
// WARNING: Hack/Experimental code only!!!
CTabHandle ctab = ::GetCTable( 555 );
ColorSpec *specs;
long i;
specs = (**ctab).ctTable;
for ( i = 0; i < 256; i++ ) {
float v = ( (float) i ) / 255.0;
v = pow( v, 1.2 );
specs[ i ].rgb.red = v * 65535;
specs[ i ].rgb.green = v * 35535;
specs[ i ].rgb.blue = v * 35535;
specs[ i ].value = i;
}
(**ctab).ctSeed = GetCTSeed();
(**mBM).pmTable = ctab;
// Restore current drawing environment
::SetGWorld( (GWorldPtr)(savePort), saveDev );
#endif
#elif EG_WIN
// Initialize a bmap info struct
mInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
mInfo.bmiHeader.biWidth = mX + 4;
mInfo.bmiHeader.biHeight = mY + 2;
mInfo.bmiHeader.biPlanes = 1;
mInfo.bmiHeader.biBitCount = inDepth;
mInfo.bmiHeader.biCompression = BI_RGB;
mInfo.bmiHeader.biSizeImage = 0;
mInfo.bmiHeader.biXPelsPerMeter = 0;
mInfo.bmiHeader.biYPelsPerMeter = 0;
mInfo.bmiHeader.biClrUsed = 0;
mInfo.bmiHeader.biClrImportant = 0;
// Tell windows to make a bitmap and give us acess to its pixel data
mBM = ::CreateDIBSection( mWorld, &mInfo, DIB_RGB_COLORS, &mBits, NULL, 0 );
HGDIOBJ oldBM = ::SelectObject( mWorld, mBM );
if ( oldBM )
::DeleteObject( oldBM );
BITMAP b;
::GetObject( mBM, sizeof( BITMAP ), &b );
mBytesPerRow = b.bmWidthBytes;
mBytesPerPix = b.bmBitsPixel / 8;
/*
mInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
mInfo.bmiHeader.biWidth = mX;
mInfo.bmiHeader.biHeight = mY;
mInfo.bmiHeader.biPlanes = 1;
mInfo.bmiHeader.biBitCount = inDepth;
mInfo.bmiHeader.biCompression = BI_RGB;
mInfo.bmiHeader.biSizeImage = 0;
mInfo.bmiHeader.biXPelsPerMeter = 39 * 96;
mInfo.bmiHeader.biYPelsPerMeter = 39 * 96;
mInfo.bmiHeader.biClrUsed = 0;
mInfo.bmiHeader.biClrImportant = 0;
*((long*) &mInfo.bmiColors) = 0;
mBytesPerPix = inDepth / 8;
mBytesPerRow = mBytesPerPix * mX;
mBuf.Dim( (mY+3) * mBytesPerRow );
mBits = mBuf.getCStr();
*/
#endif
}
void PixPort::Deactivate() {
if ( ! IsFullscreen() )
return;
#if EG_MAC && USE_DRAW_SPROCKETS
//GDHandle saveDev;
//GrafPtr savePort;
//::GetGWorld( (GWorldPtr*)(&savePort), &saveDev );
::DSpContext_FadeGamma( mContextRef, 0, NULL );
::DSpContext_SetState( mContextRef, kDSpContextState_Inactive );
::DSpContext_Release( mContextRef );
::DSpContext_FadeGamma( mContextRef, 100, NULL );
::InitCursor();
//::SetGWorld( (GWorldPtr)(savePort), saveDev );
#endif
#if USE_DIRECTX
EndFrame();
mContextRef -> Release();
mDDObj -> Release();
mDDObj = NULL;
::ReleaseCapture();
while ( ::ShowCursor( true ) < 0 ) { }
#endif
mContextRef = NULL;
}
#define __clipPt( x, y ) \
if ( x < 0 ) \
x = 0; \
else if ( x > mX ) \
x = mX; \
if ( y < 0 ) \
y = 0; \
else if ( y > mY ) \
y = mY; \
#define __clipRect( inRect ) \
Rect r = inRect; \
__clipPt( r.left, r.top ) \
__clipPt( r.right, r.bottom ) \
long width = r.right - r.left; \
long height = r.bottom - r.top;
void PixPort::BeginFrame() {
#if EG_MAC
if ( IsFullscreen() ) {
#if USE_DRAW_SPROCKETS
CGrafPtr thePort;
OSErr err;
err = ::DSpContext_GetBackBuffer( mContextRef, kDSpBufferKind_Normal, &thePort );
if ( thePort && ! err ) {
::SetPort( (GrafPtr) thePort );
mBM = thePort -> portPixMap; }
else {
mBM = NULL;
Deactivate();
}
#endif
}
else if ( mWorld )
mBM = ::GetGWorldPixMap( mWorld );
if ( mBM )
mBits = ::GetPixBaseAddr( mBM );
#endif
/*
#if USE_DIRECTX
if ( IsFullscreen() ) {
if ( ! mContextRef -> GetDC( &mFS_DC ) != DD_OK )
mFS_DC = NULL;
}
#endif*/
}
void PixPort::EndFrame() {
if ( IsFullscreen() ) {
#if USE_DRAW_SPROCKETS
::DSpContext_SwapBuffers( mContextRef, NULL, 0 );
#endif
#if USE_DIRECTX && 0
if ( mFS_DC ) {
mContextRef -> ReleaseDC( mFS_DC );
mFS_DC = NULL;
}
#endif
}
}
long PixPort::GetPortColor( long inR, long inG, long inB ) {
int bitDepth =mBytesPerPix << 3;
long c;
if ( inR > 0xFFFF ) inR = 0xFFFF;
if ( inG > 0xFFFF ) inG = 0xFFFF;
if ( inB > 0xFFFF ) inB = 0xFFFF;
if ( inR < 0 ) inR = 0;
if ( inG < 0 ) inG = 0;
if ( inB < 0 ) inB = 0;
if ( bitDepth == 32 )
c = __Clr32( inR, inG, inB );
else if ( bitDepth == 16 )
c = __Clr16( inR, inG, inB );
else
c = __Clr8( inR, inG, inB );
return c;
}
long PixPort::SetBackColor( const RGBColor& RGB ) {
mBackColor = GetPortColor( RGB );
return mBackColor;
}
long PixPort::SetBackColor( long inR, long inG, long inB ) {
mBackColor = GetPortColor( inR, inG, inB );
return mBackColor;
}
void PixPort::GaussBlur( int inBoxWidth, const Rect& inRect, void* inDestBits ) {
// Don't let us draw in random parts of memory -- clip inRect
__clipRect( inRect )
if ( inBoxWidth <= 1 )
return;
// In Win32, everything's upside down
#if EG_WIN
r.top = mY - r.bottom;
#endif
// 3 box convolutions, 3 colors per pixel, 4 bytes per color
long boxTempSize = 36 * inBoxWidth;
char* tempBits = NULL;
unsigned long* boxTemp;
long imgOffset = mBytesPerPix * r.left + r.top * mBytesPerRow;
long bytesNeeded = mBytesPerRow * (mY + 2) + boxTempSize;
#if EG_MAC
if ( mHndlSize < bytesNeeded ) {
OSErr err;
if ( mTempHndl ) {
::TempDisposeHandle( mTempHndl, &err );
mHndlSize = 0;
}
mTempHndl = ::TempNewHandle( bytesNeeded, &err );
if ( ! err ) {
tempBits = *mTempHndl;
mHndlSize = bytesNeeded;
}
}
#endif
// Resort to app's heap for temp mem if failed temp mem attempt or in win32
if ( ! tempBits ) {
mTempBuf.Dim( bytesNeeded );
tempBits = mTempBuf.getCStr();
}
// Have the box temp and the pixel temp rgns use the same handle
boxTemp = (unsigned long*) tempBits;
tempBits += boxTempSize;
if ( ! inDestBits )
inDestBits = mBits;
// Do a box blur on the x axis, transposing the source rgn to the dest rgn
// Then o a box blur on the transposed image, effectively blurring the y cords, transposing it to the dest
if ( mBytesPerPix == 2 ) {
BoxBlur16( ( mBits + imgOffset), tempBits, inBoxWidth, width, height, mBytesPerRow, mBytesPerPix*height, boxTemp, mBackColor );
BoxBlur16( tempBits, ((char*) inDestBits + imgOffset), inBoxWidth, height, width, mBytesPerPix*height, mBytesPerRow, boxTemp, mBackColor ); }
else if ( mBytesPerPix == 4 ) {
BoxBlur32( ( mBits + imgOffset), tempBits, inBoxWidth, width, height, mBytesPerRow, mBytesPerPix*height, boxTemp, mBackColor );
BoxBlur32( tempBits, ((char*) inDestBits + imgOffset), inBoxWidth, height, width, mBytesPerPix*height, mBytesPerRow, boxTemp, mBackColor );
}
}
void PixPort::CrossBlur( const Rect& inRect ) {
// Don't let us draw in random parts of memory -- clip inRect
__clipRect( inRect )
// In Win32, everything's upside down
#if EG_WIN
r.top = mY - r.bottom;
#endif
// 3 box convolutions, 3 colors per pixel, 4 bytes per color
long imgOffset = mBytesPerPix * r.left + r.top * mBytesPerRow;
mTempBuf.Dim( mX * 3 );
unsigned char* tempBits = (unsigned char*) mTempBuf.getCStr();
if ( mBytesPerPix == 2 )
CrossBlur16( ( mBits + imgOffset), width, height, mBytesPerRow, tempBits );
else if ( mBytesPerPix == 4 )
CrossBlur32( ( mBits + imgOffset), width, height, mBytesPerRow, tempBits );
}
void PixPort::CopyBits( WindowPtr inDest, const Rect* inSrce, const Rect* inDestRect ) {
#if EG_MAC
::CopyBits( (BitMap*) *mBM, &inDest->portBits, inSrce, inDestRect, srcCopy, NULL );
#elif EG_WIN
HDC hdc = ::GetDC( inDest );
::BitBlt( hdc, inDestRect -> left, inDestRect -> top, inDestRect -> right - inDestRect -> left, inDestRect -> bottom - inDestRect -> top, mWorld, inSrce -> left, inSrce -> top, SRCCOPY );
::ReleaseDC( inDest, hdc );
#endif
}
void PixPort::Line( int sx, int sy, int ex, int ey, long inColor ) {
if ( mBytesPerPix == 2 )
Line16( sx, sy, ex, ey, inColor );
else if ( mBytesPerPix == 1 )
Line8 ( sx, sy, ex, ey, inColor );
else if ( mBytesPerPix == 4 )
Line32( sx, sy, ex, ey, inColor );
}
void PixPort::Line( int sx, int sy, int ex, int ey, const RGBColor& inS, const RGBColor& inE ) {
long R, G, B, dR, dG, dB, absdR, absdG, absdB;
R = inS.red;
G = inS.green;
B = inS.blue;
dR = inE.red - R;
dG = inE.green - G;
dB = inE.blue - B;
absdR = dR & 0x7FFFFFFF; // Abs value
absdG = dG & 0x7FFFFFFF;
absdB = dB & 0x7FFFFFFF;
// If the endpoints have the same color, run the faster line procs (that just use one color)
if ( absdR < 520 && absdG < 520 && absdB < 520 ) {
long color;
if ( mBytesPerPix == 2 ) {
color = __Clr16( R, G, B );
Line16( sx, sy, ex, ey, color ); }
else if ( mBytesPerPix == 4 ) {
color = __Clr32( R, G, B );
Line32( sx, sy, ex, ey, color ); }
else if ( mBytesPerPix == 1 ) {
color = __Clr8( R, G, B );
Line8 ( sx, sy, ex, ey, color );
} }
else {
if ( mBytesPerPix == 2 )
Line16( sx, sy, ex, ey, inS, dR, dG, dB );
else if ( mBytesPerPix == 4 )
Line32( sx, sy, ex, ey, inS, dR, dG, dB );
else if ( mBytesPerPix == 1 )
Line8 ( sx, sy, ex, ey, inS, dR, dG, dB );
}
}
void PixPort::SetLineWidth( long inLineWidth ) {
if ( inLineWidth <= 0 )
mLineWidth = 1;
else if ( inLineWidth > MAX_LINE_WIDTH )
mLineWidth = MAX_LINE_WIDTH;
else
mLineWidth = inLineWidth;
}
void PixPort::EraseRect( const Rect* inRect ) {
if ( mBytesPerPix == 2 )
EraseRect16( inRect );
else if ( mBytesPerPix == 1 )
EraseRect8 ( inRect );
else if ( mBytesPerPix == 4 )
EraseRect32( inRect );
}
#define P_SZ 1
#include "DrawXX.cpp"
#undef P_SZ
#define P_SZ 2
#include "DrawXX.cpp"
#undef P_SZ
#define P_SZ 4
#include "DrawXX.cpp"
/*
#define HALFCORD 0x007F /* 16 bits per cord, 8 bits for fixed decimal -> means +/- 127
#define __loadGrad g = *((unsigned long*) inGrad); \
xsrc = g >> 24; \
ysrc = (g >> 8) & 0xFF;
#define __calcP v = g & 0xFF; /* x - xsrc \
u = (g >> 16) & 0xFF; /* y - ysrc \
u1 = 0x100 - u; /* 1 - u \
p = v * ( P3 * u1 + P4 * u ) + ( 0x100 - v ) * ( P1 * u1 + P2 * u );
#define __loadPX P1 = *((unsigned short*) srceMap); \
P2 = P1 & 0xFF; \
P1 = P1 >> 8; \
P3 = *((unsigned short*) (srceMap + mBytesPerRow)); \
P4 = P3 & 0xFF; \
P3 = P3 >> 8; \
/*
void PixPort::Fade( PixPort& ioDest, void* inGrad ) {
unsigned long g, p, x, y, xsrc, ysrc, u, v, u1, P1, P2, P3, P4, finalP;
char* dest, *srceBase, *srceMap, *prevMap;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
long blah;
long* bptr = &blah;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y++ ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
for ( x = 0; x < mX; x += 4 ) {
// Extract the gradient information
__loadGrad
// P1 - P2
// | |
// P3 - P4
srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
__loadPX
__calcP
finalP = (p & 0xFFFF0000) << 8;
// **** x + 1
prevMap = srceMap;
__loadGrad
srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 1;
// If we don't already have the four fence pixels, load them from RAM
if ( srceMap != prevMap ) {
__loadPX
}
__calcP
finalP |= (p & 0x00FF0000);
// **** x + 2
prevMap = srceMap;
__loadGrad
srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 2;
// If we don't already have the four fence pixels, load them from RAM
if ( srceMap != prevMap ) {
__loadPX
}
__calcP
finalP |= (p & 0xFFFF0000) >> 8;
// **** x + 3
prevMap = srceMap;
__loadGrad
srceMap = srceBase + xsrc + ysrc * mBytesPerRow + 3;
// If we don't already have the four fence pixels, load them from RAM
if ( srceMap != prevMap ) {
__loadPX
}
__calcP
finalP |= p >> 16;
*((unsigned long*) dest) = finalP;
// Move to x+4
inGrad = ((long*) inGrad) + 4;
srceBase += 4;
dest += 4;
}
}
}
*/
#define HALFCORD 0x001F /* 12 bits per cord, 5 bits for fixed decimal -> means +/- 127 */
void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
unsigned long p, x, y, u, v, u1, v1, P1, P2, P3, P4, bytesPerRow, codedDel, xGrad, yGrad;
char* dest, *srceBase, *srceMap, *prevLoc = 0;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
bytesPerRow = mBytesPerRow;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y++ ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
for ( x = 0; x < mX; x++ ) {
// Extract the gradient information
// Format of a grad short: ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
codedDel = *((unsigned long*) inGrad);
inGrad += 3;
xGrad = codedDel >> 20;
yGrad = 0xFFF & ( codedDel >> 8 );
// Get the vector to the source pixel
srceMap = srceBase + ( xGrad >> 6 ) + ( yGrad >> 6 ) * bytesPerRow;
u = ( yGrad & 0x3F ); // y - ysrc
v = ( xGrad & 0x3F ); // x - xsrc
srceBase++;
// P1 - P2
// | |
// P3 - P4
P1 = ( (unsigned char*) srceMap )[0];
P2 = ( (unsigned char*) srceMap )[1];
u1 = 0x40 - u;
P1 *= u1;
P2 *= u1;
P3 = ( (unsigned char*) srceMap )[ bytesPerRow ];
P4 = ( (unsigned char*) srceMap )[ bytesPerRow + 1 ];
v1 = 0x40 - v;
P3 *= u;
P4 *= u;
// Bilinear interpolation to approximate the source pixel value
p = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
// Store the calculated/dest pixel (rounding the fraction part of the pix value)
// We divide by 12 decimal places because p is units squared (6 places per decimal)
*((unsigned char*) dest) = ( 15 * p ) >> 16; dest++; // 5 more dec places cuz of the mult by 31
}
}
}
/*
void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
unsigned long p, x, y, u, v, u1, v1, P1, P2, P3, P4, bytesPerRow;
char* dest, *srceBase, *srceMap, *prevLoc = 0;
long destRowBytes = ioDest.mBytesPerRow, xGrad, yGrad;
if ( mBytesPerPix != 1 )
return;
bytesPerRow = mBytesPerRow;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y++ ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
for ( x = 0; x < mX; x++ ) {
// Extract the gradient information
// Format of a grad short: ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
xGrad = *( (char*) inGrad ); inGrad++;
yGrad = *( (char*) inGrad ); inGrad++;
// Get the vector to the source pixel
srceMap = srceBase + ( xGrad >> 2 ) + ( yGrad >> 2 ) * bytesPerRow;
u = ( yGrad & 0x3 ); // y - ysrc
v = ( xGrad & 0x3 ); // x - xsrc
srceBase++;
// P1 - P2
// | |
// P3 - P4
P1 = ( (unsigned char*) srceMap )[0];
P2 = ( (unsigned char*) srceMap )[1];
u1 = 0x4 - u;
P1 *= u1;
P2 *= u1;
P3 = ( (unsigned char*) srceMap )[ bytesPerRow ];
P4 = ( (unsigned char*) srceMap )[ bytesPerRow + 1 ];
v1 = 0x4 - v;
P3 *= u;
P4 *= u;
// Bilinear interpolation to approximate the source pixel value
p = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
// Store the calculated/dest pixel (rounding the fraction part of the pix value)
// We divide by 4 decimal places because p is units squared
*((unsigned char*) dest) = ( 31 * p ) >> 9; dest++; // 5 more dec places cuz of the mult by 31
}
}
}*/
/*
void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
unsigned long gDelta, p, x, y, u, v, u1, v1, P1, P2, P3, P4;
char* dest, *srceBase, *srceMap, *prevLoc = 0;
long destRowBytes = ioDest.mBytesPerRow, xGrad, yGrad;
if ( mBytesPerPix != 1 )
return;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y++ ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + y * mBytesPerRow;
for ( x = 0; x < mX; x++ ) {
// Extract the gradient information
// Format of a grad short: ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
gDelta = *((long*) inGrad);
inGrad += 3;
xGrad = ( (long) ( gDelta >> 20 ) ) - 0x7FF;
yGrad = ( (long) ( ( gDelta >> 8 ) & 0xFFF ) ) - 0x7FF;
// Get the vector to the source pixel
srceMap = srceBase + ( xGrad >> 2 ) + ( yGrad >> 2 ) * mBytesPerRow;
u = yGrad & 0x3; // y - ysrc
v = xGrad & 0x3; // x - xsrc
srceBase++;
// P1 - P2
// | |
// P3 - P4
P1 = *((unsigned short*) srceMap);
P3 = *((unsigned short*) (srceMap + mBytesPerRow));
u1 = 0x4 - u;
P2 = ( P1 & 0xFF ) * u1;
P1 = ( P1 >> 8 ) * u1;
v1 = 0x4 - v;
P4 = ( P3 & 0xFF ) * u;
P3 = ( P3 >> 8 ) * u;
// Bilinear interpolation to approximate the source pixel value
p = v * ( P2 + P4 ) + v1 * ( P1 + P3 );
// Store the calculated/dest pixel (rounding the fraction part of the pix value)
// We divide by 10 decimal places because p is units squared
*((unsigned char*) dest) = p >> 4;
// Move to x+1
dest++;
}
}
}
*/
/*
void PixPort::Fade( PixPort& ioDest, char* inGrad ) {
unsigned long gDelta, xGrad, yGrad, p, x, y, u, v, u1, P1, P2, P3, P4;
char* dest, *srceBase, *srceMap, *prevLoc = 0;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y++ ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD;
for ( x = 0; x < mX; x++ ) {
// Extract the gradient information
// Format of a grad short: ( ( (ddx + 128) * 16 ) << 20 ) | ( (ddy + 128) * 16 ) << 8
gDelta = *((long*) inGrad);
inGrad += 3;
xGrad = ( gDelta >> 20 );
yGrad = ( ( gDelta >> 8 ) & 0xFFF );
// Get the vector to the source pixel
srceMap = srceBase + ( xGrad >> 5 ) + ( yGrad >> 5 ) * mBytesPerRow;
// P1 - P2
// | |
// P3 - P4
P1 = *((unsigned short*) srceMap);
P2 = P1 & 0xFF;
P1 = P1 >> 8;
P3 = *((unsigned short*) (srceMap + mBytesPerRow));
P4 = P3 & 0xFF;
P3 = P3 >> 8;
// Bilinear interpolation to approximate the source pixel value
v = xGrad & 0x1F; // x - xsrc
u = yGrad & 0x1F; // y - ysrc
u1 = 0x20 - u; // 1 - u
p = v * ( P2 * u1 + P4 * u ) + ( 0x1F - v ) * ( P1 * u1 + P3 * u );
// Store the calculated/dest pixel (rounding the fraction part of the pix value)
// We divide by 10 decimal places because p is units squared
*((unsigned char*) dest) = p >> 10;
// Move to x+1
dest += 1;
srceBase += 1;
}
}
}*/
/*
#define XSHIFT 10
#define HALFCORD 0x001F /* 16 bits per cord, 8 bits for fixed decimal -> means +/- 127
#define CORDMASK 0x003F /* 6 bits per cord
#define DECAYSHIFT 6 /* 4 bits left for the intensity decay factor
#define DECAYMASK 0x000F
#define __fade( t, r, b) t1 = (r >> 16) & 0xFF; \
t2 = (r >> 8) & 0xFF; \
pleft = (t >> 24) + (b >> 24) + ((t >> 8) & 0xFF) + ((b >> 8) & 0xFF); \
prght = ((t >> 16) & 0xFF) + (t & 0xFF) + ((b >> 16) & 0xFF) + (b & 0xFF); \
pleft = 2 * (r >> 24) + 2 * ((r >> 8) & 0xFF); \
prght = 2 *((r >> 16) & 0xFF) + 2 * (r & 0xFF); \
pleft = ( pleft + 8 * t1 ) / 20; \
prght = ( prght + 8 * t2 ) / 20;
void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
unsigned long g, t, b, r1, pleft, prght, x, y, xsrc, ysrc, t1, t2;
char* dest, *srceBase, *srceMap;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
long blah;
long* bptr = &blah;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y += 1 ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
for ( x = 0; x < mX; x += 2 ) {
// Extract the gradient information
g = *((unsigned short*) inGrad);
if ( y > 250 ) {
g = HALFCORD | (HALFCORD << XSHIFT);
}
xsrc = g >> XSHIFT;
ysrc = g & CORDMASK;
srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
t = *((unsigned long*) (srceMap - mBytesPerRow));
r1 = *((unsigned long*) srceMap);
b = *((unsigned long*) (srceMap + mBytesPerRow));
__fade( t, r1, b )
//pleft = t + b;
//prght = r1;
*((unsigned short*) dest) = (pleft << 8) | prght;
//*((unsigned long*) bptr) = (pleft << 8) | prght;
// Move to x+1
inGrad++;
dest += 2;
srceBase += 2;
}
}
}
*/
/*
#define __fade( t, r, b) t1 = (r >> 16) & 0xFF; \
t2 = (r >> 8) & 0xFF; \
pleft = ( ((t >> 8) & 0xFF) + ((b >> 8) & 0xFF) + (r >> 24) + 4 * t1 + t2 ) / 8; \
prght = ( (t & 0xFF) + (b & 0xFF) + t1 + 4 * t2 + (r & 0xFF) ) / 8;
void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
unsigned long g, t, b, r1, pleft, prght, x, y, xsrc, ysrc, t1, t2;
char* dest, *srceBase, *srceMap;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y += 1 ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
for ( x = 0; x < mX; x += 2 ) {
// Extract the gradient information
g = *((unsigned short*) inGrad);
if ( y > 250 ) {
g = HALFCORD | (HALFCORD << XSHIFT);
}
xsrc = g >> XSHIFT;
ysrc = g & CORDMASK;
srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
t = *((unsigned short*) (srceMap - mBytesPerRow + 1));
r1 = *((unsigned long*) srceMap);
b = *((unsigned short*) (srceMap + mBytesPerRow + 1));
__fade( t, r1, b )
*((unsigned short*) dest) = (pleft << 8) | prght;
// Move to x+1
inGrad++;
dest += 2;
srceBase += 2;
}
}
}
*/
/*
#define __fade( r ) t1 = (r >> 16) & 0xFF; \
t2 = (r >> 8) & 0xFF; \
pleft = ( (r >> 24) + 8 * t1 + t2 ) / 11; \
prght = ( t1 + 8 * t2 + (r & 0xFF) ) / 11;
void PixPort::Fade( PixPort& ioDest, short* inGrad ) {
unsigned long g, r1, r2, pleft, prght, x, y, xsrc, ysrc, t1, t2;
char* dest, *srceBase, *srceMap;
long destRowBytes = ioDest.mBytesPerRow;
if ( mBytesPerPix != 1 )
return;
// For every pixel in the destination, find it's source via the gradient
for ( y = 0; y < mY; y += 2 ) {
// Setup the dest row base address
dest = ioDest.mBits + destRowBytes * y;
// Setup the source row base address, also offset to allow for negative grad components
srceBase = mBits + ( y - HALFCORD ) * mBytesPerRow - HALFCORD - 1;
for ( x = 0; x < mX; x += 2 ) {
// Extract the gradient information
g = *((unsigned short*) inGrad);
if ( y > 250 ) {
g = HALFCORD | (HALFCORD << XSHIFT);
}
xsrc = g >> XSHIFT;
ysrc = g & CORDMASK;
srceMap = srceBase + xsrc + ysrc * mBytesPerRow;
r1 = *((unsigned long*) srceMap);
r2 = *((unsigned long*) (srceMap + mBytesPerRow));
__fade( r1 )
*((unsigned short*) dest) = (pleft << 8) | prght;
__fade( r2 )
*((unsigned short*) (dest + destRowBytes)) = (pleft << 8) | prght;
// Move to x+1
inGrad++;
dest += 2;
srceBase += 2;
}
}
}*/
// Random code segments that were tried/experimented with and tossed...
/*
int w, t, dx = ex - sx, dy = ey - sy, xDirection, yDirection, error_term;
// Let a dot have a slope of 0
if ( dx == 0 && dy == 0 )
dx = 1;
// Make sure we have a long enough path to step thru
dx *= mLineWidth;
dy *= mLineWidth;
// Extend the line by w/2 at the endpoints
movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
movePt( ex, ey, dx, dy, mLineWidth / 2 );
// Offset the line w/2
movePt( sx, sy, dy, -dx, mLineWidth / 2 );
movePt( ex, ey, dy, -dx, mLineWidth / 2 );
int tx = sx, ty = sy;
movePt( tx, ty, dx, dy, mLineWidth * dy / dx );
for ( ; sy < tx; sy++ ) {
if ( mBytesPerPix == 2 )
Line16( sx, sy, ex, ey, inColor, 0 );
else if ( mBytesPerPix == 4 )
Line32( sx, sy, ex, ey, inColor, 0 );
else if ( mBytesPerPix == 1 )
Line8 ( sx, sy, ex, ey, inColor, 0 );
}*/
/*
int w, t, dx = ex - sx, dy = ey - sy, xDirection, yDirection, error_term;
// Let a dot have a slope of 0
if ( dx == 0 && dy == 0 )
dx = 1;
// Make sure we have a long enough path to step thru
dx *= mLineWidth;
dy *= mLineWidth;
// Offset the line w/2
movePt( sx, sy, dy, -dx, mLineWidth / 2 );
movePt( ex, ey, dy, -dx, mLineWidth / 2 );
// Extend the line by w/2 at the endpoints
movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
movePt( ex, ey, dx, dy, mLineWidth / 2 );
t = dx; dx = -dy; dy = t;
// moving left or right?
if ( dx < 0 ) {
xDirection = -1;
dx = -dx; }
else if ( dx > 0 )
xDirection = 1;
else
xDirection = 0;
// moving up or down?
if ( dy < 0 ) {
yDirection = -1;
dy = -dy; }
else if ( dy > 0 )
yDirection = 1;
else
yDirection = 0;
error_term = 0;
// Walf thru the width
for ( w = 0; w < mLineWidth; w++ ) {
if ( dx >= dy ) {
sx += xDirection;
ex += xDirection;
// Check to see if we need to move the pixelOffset in the y direction.
error_term += dy;
if ( error_term > dx ) {
error_term -= dx;
sy += yDirection;
ey += yDirection;
} }
else {
sy += yDirection;
ey += yDirection;
// Check to see if we need to move the pixelOffset in the y direction.
error_term += dx;
if ( error_term > dy ) {
error_term -= dy;
sx += xDirection;
ex += xDirection;
}
}
if ( mBytesPerPix == 2 )
Line16( sx, sy, ex, ey, inColor, 0 );
else if ( mBytesPerPix == 4 )
Line32( sx, sy, ex, ey, inColor, 0 );
else if ( mBytesPerPix == 1 )
Line8 ( sx, sy, ex, ey, inColor, 0 );
}
}*/
/*
void PixPort::LineW( int sx, int sy, int ex, int ey, long inColor ) {
int i;
int dx = ex - sx;
int dy = ey - sy;
// Let a dot have a slope of 0
if ( dx == 0 && dy == 0 )
dx = 1;
// Make sure we have a long enough path to step thru
dx *= mLineWidth;
dy *= mLineWidth;
// Extend the line by w/2 at the endpoints
movePt( sx, sy, -dx, -dy, mLineWidth / 2 );
movePt( ex, ey, dx, dy, mLineWidth / 2 );
// Offset the line w/2
movePt( sx, sy, dy, -dx, mLineWidth / 2 );
movePt( ex, ey, dy, -dx, mLineWidth / 2 );
if ( dx < 0 )
dx = -dx;
if ( dy < 0 )
dy = -dy;
// For near horizontal slopes, draw multiple horizontal lines
if ( dy != 0 ) {
if ( dx / dy > 5 )
dy = 0;
}
if ( mLineWidth + 3 < dy ) {
float fdy = ((float) dy) * ((float) dy);
float fdx = ((float) dx) * ((float) dx);
int w = ((float) mLineWidth) * sqrt( (1.0 + fdx / fdy) ) + 0.31;
LineW16( sx, sy, ex, ey, w, inColor ); }
else {
sy -= mLineWidth / 2; ey -= mLineWidth / 2;
for ( i = 0; i < mLineWidth; i++ ) {
Line16( sx, sy, ex, ey, inColor );
sy++;
ey++;
}
}
// Find xleft
// Set the scane width's worth of pixels from xlefr
// Fill bottom triangle
}
void PixPort::movePt( int& ioX, int& ioY, int dx, int dy, int inDist ) {
int i, xDirection, yDirection, error_term;
// moving left or right?
if ( dx < 0 ) {
xDirection = -1;
dx = -dx; }
else if ( dx > 0 )
xDirection = 1;
else
xDirection = 0;
// moving up or down?
if ( dy < 0 ) {
yDirection = -1;
dy = -dy; }
else if ( dy > 0 )
yDirection = 1;
else
yDirection = 0;
error_term = 0;
if ( dx >= dy ) {
// Start counting off in x
for ( i = 0; i < inDist; i++) {
ioX += xDirection;
// Check to see if we need to move the pixelOffset in the y direction.
error_term += dy;
if ( error_term >= dx ) {
error_term -= dx;
ioY += yDirection;
}
} }
else {
// Start counting off in y
for ( i = 0; i <= inDist; i++) {
ioY += yDirection;
// Check to see if we need to move the pixelOffset in the y direction.
error_term += dx;
if ( error_term >= dy ) {
error_term -= dy;
ioX += xDirection;
}
}
}
}
*/